//
//  main.m
//  08-IOS9新特性(Nullability,泛型,_kindof)
//
//  Created by dllo on 16/7/13.
//  Copyright © 2016年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *per = [[Person alloc] init];
//        per.name = nil;
//        [per setName:<#(NSString * _Nonnull)#>]
//        [per name]
        // nonullability
        //nonull 修饰时 get set 方法返回值,参数,需要非空
        NSString *str = nil;
        per.name = str;
        // 系统无法识别变量,只有直观的空值才被检测到
        per.name = @"afhwfh";
//        [per setSex:<#(NSString * _Nullable)#>]
        //nullable 修饰时 get set 方法返回值,参数,可以为空
//        [per setAddress:<#(NSString * _Nonnull)#>]
        
        
        // null_resettable
//        [per setFriends:<#(NSArray * _Nullable)#>]
//        [per friends]
//        setter方法 可以为空,getter方法 不能为空
        // 赋值可以为空,取值必须为非空
        // 举例:UIViewController中的view属性(懒加载)
        
        
        
        // 泛型
        // 带泛型的容器
        // 声明一个可变数组,内部存放的都是字符串
        // 好处:
        // 数组中添加其他类型,会有警告
        // 数组取出来的类型不再是id类型,对应变成声明时的类型
        NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"2", @"1" ,@"ass", nil];
//        [array addObject:<#(nonnull NSString *)#>];
//        [array objectAtIndex:<#(NSUInteger)#>]
        // id类型点不出来属性,用了尖括号泛型可以知道类型,能点出来
//        array.firstObject.length
//        等价于
//        NSString *str = array.firstObject;
//        str.length
        // <NSString *> 数组里只存字符串
        NSMutableArray *array1 = [NSMutableArray array];
//        [array1 addObject:<#(nonnull id)#>]
//        [array1 objectAtIndex:<#(NSUInteger)#>]
        NSInteger integer = [array objectAtIndex:0].length;
        
        // 带泛型的字典
        NSMutableDictionary<NSString *,NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"于涵", @"name", nil];
//        [dic objectForKey:@"name"].length;
        // 自定义泛型
        // 声明后,可以应用于属性,方法中
        // 泛型名 等效于 类型修饰 (例:NSString *)
        Truck<Person *> *truck = [[Truck alloc] init];
         Student *stu = [[Student alloc] init];
        // 卡车(person)
        [truck addObject:per];
         [truck addObject:stu];
        // 学生继承了人,卡车(person)既能放人又能放学生,
       
        Truck<Student *> *truckStu = [[Truck alloc] init];
        // 卡车(student)
        // 只能放学生
        [truckStu addObject:stu];
//        [truckStu addObject:per]; 类不对
//        [truck firstObject] 返回值
        
        
        // 大类型可以被任意类型赋值,或者赋值给任意类型
        Truck *truck1 = [[Truck alloc] init];
        truck1 = truck;
        // __convariant 协变性 子类在给弗雷赋值时,可以自动强转
        // Truck<NSArray *> 与 Truck<NSMutableArray *>
        // __contravariant 逆变性,父类给子类赋值,自动强转(暂时不知用处)
        
        // 3.__kindof
        // 加__kindof 不需要写强转
        
        
    }
    return 0;
}

